package myJs

import myJs.Utils.g
import myJs.myPkg._

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.myPkg.Implicits._
import org.scalajs.dom.ext.Ajax

import scala.scalajs.js.JSON
import myJs.implicits.Implicits._

import scala.concurrent.ExecutionContext.Implicits.global
import myJs.myPkg.jquery.{JQuery, _}
import myJs.Utils._
import org.scalajs.dom.{Element, Event, FormData, document}

import scala.collection.immutable.SeqMap
import myJs.implicits.Implicits._
import scalatags.Text.all._

import scala.scalajs.js.JSConverters._
import implicits.Implicits._
import shared.VarTool


/**
 * Created by yz on 11/5/2020
 */
@JSExportTopLevel("Browse")
object Browse {

  val tableId = "table"


  @JSExport("init")
  def init = {
    refreshGeneType.zip(refreshJunctionType).zip(refreshAnnotation).zip(refreshTumorTypes).map { x =>
      refreshOrder
      refreshSort
      refreshTumorTypesMethod
      initTable
    }

  }

  def getKind = {
    g.kind.toString
  }

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case "geneSymbol" => val url = g.jsRoutes.controllers.SearchController.searchResultBefore().url.toString
      a(href := s"${url}?keyword=${v}", cursor.pointer, target := "_blank",
        v.toString
      )
    case "junctionId" =>
      val kind = Tool.junctionTypeAbbrMap(row("junctionType").toString)
      val url = g.jsRoutes.controllers.SearchController.detailInfoBefore().url.toString
      a(title := "detail", href := s"${url}?junctionId=${v}&kind=${kind}", cursor.pointer, target := "_blank",
        v.toString
      )
    case _ => if (v.toString.isDouble) {
      v.toString.toDouble.toFixed(Tool.decDigits)
    } else v
  }

  def ajaxRequest: js.Function = (params: js.Dictionary[js.Any]) => {
    val url = g.jsRoutes.controllers.BrowseController.getAllJunctionByServer().url.toString
    val dataMap = params("data").toString.toJDS.toMap
    val queryMap: Map[String, js.Any] = Map(
      "geneTypes" -> Tool.getInputByName("geneTypes").select2Val,
      "junctionTypes" -> Tool.getInputByName("junctionTypes").select2Val,
      "annotations" -> Tool.getInputByName("annotations").select2Val,
      "tumorTypes" -> Tool.getInputByName("tumorTypes").select2Val,
      "sort" -> Tool.getInputByName("sort").select2Val.head,
      "order" -> Tool.getInputByName("order").select2Val.head,
      "tumorTypesMethod" -> Tool.getInputByName("tumorTypesMethod").select2Val.head,
    )
    val dataDict = (dataMap ++ queryMap).toJSDictionary
    val data = JSON.stringify(dataDict)
    Ajax.post(url = s"${url}", data = data, headers = Map("Content-Type" -> "application/json"),
      responseType = "application/json").map { xhr =>
      val json = xhr.responseText.toJDJAn
      val successF = params("success").asInstanceOf[js.Function1[js.Any, js.Any]]
      successF(json)
    }
  }

  def initTable = {
    val map = VarTool.junctionMap
    val columnNames = map.keyList
    val columns = columnNames.map { columnName =>
      val title = map.getOrElse(columnName, columnName)
      val fmt = tbFmt(columnName)
      val basicOptions = ColumnOptions.field(columnName).title(title).formatter(fmt)
      val datepickerOptions: js.Dictionary[js.Any] = js.Dictionary("format" -> Tool.pattern, "language" -> "zh-CN",
        "autoclose" -> true)
      columnName match {
        case _ => basicOptions
      }
    }
    val url = g.jsRoutes.controllers.BrowseController.getAllJunctionByServer().url.toString
    val exportOptions = ExportOptions.fileName("junction.csv")
    val options = TableOptions.columns(columns.toJSArray).method("post").sidePagination("server").ajax(ajaxRequest).
      exportOptions(exportOptions).showExport(true).exportDataType("all").exportTypes(js.Array("csv")).search(true)
    $(s"#${tableId}").bootstrapTable(options)

    $("li[data-type='csv']").off("click").on("click", () => {
      val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
      val ids = $(s"#${tableId}").bootstrapTable("getData", js.Dictionary("useCurrentPage" -> true)).
        toJArJDS.map { x =>
        x("junctionId")
      }
      val dict = Map(
        "junctionIds" -> ids
      ).toJSDictionary
      val url = g.jsRoutes.controllers.BrowseController.downloadAllJunction().url.toString
      Ajax.post(url = s"${url}", data = JSON.stringify(dict), headers = Map("Content-Type" -> "application/json"),
        responseType = "blob").map {
        xhr =>
          layer.close(index)
          Tool.downloadCsv(s"junction.csv", xhr.response)
      }
    })

    Tool.refreshCheckboxView(map.tail, "checkbox")
    val hideColumns = map.keyList.filterNot { x =>
      List("junctionId", "junctionLocation", "junctionType", "geneSymbol", "geneType", "tumorMedian", "tumorFreq",
        "tumorSpecificTypes", "annotation").contains(x)
    }
    hideColumns.foreach { x =>
      $("#table").bootstrapTable("hideColumn", x)
      $(s"input:checkbox[value='${x}']").attr("checked", false)
    }
    bindEvt

  }

  def bindEvt = {

  }

  def execBrowse = {
    $("#table").bootstrapTable("refresh")
  }

  def refreshGeneType = {
    val url = g.jsRoutes.controllers.BrowseController.getAllGeneTypes().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("geneTypes").select2(options)
    }
  }

  def refreshSort = {
    val names = List("", "tumorMedian", "ntMedian", "normalMedian", "tumorFreq", "ntFreq", "normalFreq")
    val data = names.map { x =>
      (x -> VarTool.junctionMap.getOrElse(x, ""))
    }
    val array = data.map { case (id, text) =>
      js.Dictionary("text" -> text, "id" -> id)
    }
    val options = Select2Options.allowClear(true).placeholder("click to choose").dictData(array.toJSArray)
    Tool.getInputByName("sort").select2(options)
  }

  def refreshTumorTypesMethod = {
    val data = SeqMap("union" -> "Union", "inter" -> "Intersection")
    val array = data.map { case (id, text) =>
      js.Dictionary("text" -> text, "id" -> id)
    }
    val options = Select2Options.dictData(array.toJSArray)
    Tool.getInputByName("tumorTypesMethod").select2(options)
  }

  def refreshOrder = {
    val data = SeqMap("asc" -> "Asc", "desc" -> "Desc")
    val array = data.map { case (id, text) =>
      js.Dictionary("text" -> text, "id" -> id)
    }
    val options = Select2Options.dictData(array.toJSArray)
    Tool.getInputByName("order").`val`("asc").select2(options)
  }

  def refreshJunctionType = {
    val url = g.jsRoutes.controllers.BrowseController.getAllJunctionTypes().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("junctionTypes").select2(options)
      val selectVs = getKind match {
        case "ls" => js.Array("Linear")
        case "bs" => js.Array("Back-splice")
        case "fs" => js.Array("Fusion")
        case _ => js.Array[String]()
      }
      if (selectVs.nonEmpty) {
        Tool.getInputByName("junctionTypes").select2Val(selectVs)
      }
    }
  }

  def refreshAnnotation = {
    val url = g.jsRoutes.controllers.BrowseController.getAllAnnotation().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("annotations").select2(options)
      val selectVs = getKind match {
        case "unAno" => data.toList.filterNot { x => List("yes").contains(x) }.toJSArray
        case _ => js.Array[String]()
      }

      if (selectVs.nonEmpty) {
        Tool.getInputByName("annotations").select2Val(selectVs)
      }
    }
  }

  def refreshTumorTypes = {
    val url = g.jsRoutes.controllers.BrowseController.getAllTumorTypes().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("tumorTypes").select2(options)
      val selectVs = getKind match {
        case "tsj" => data.toList.filterNot { x => List("-", "non tumor-specific").contains(x) }.toJSArray
        case _ => js.Array[String]()
      }

      if (selectVs.nonEmpty) {
        Tool.getInputByName("tumorTypes").select2Val(selectVs)
        Tool.getInputByName("junctionTypes").select2Val(js.Array("Linear"))
      }
    }
  }

  @JSExport("myRun")
  def myRun = {
    val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
    $("#table").bootstrapTable("refresh")
    layer.close(index)
  }


}
